package com.hqyj.service.impl;

import com.hqyj.exception.R;
import com.hqyj.pojo.TestStock;
import com.hqyj.service.TestRedisService;
import com.hqyj.service.TestStockService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class TestRedisServiceImpl implements TestRedisService {
    @Autowired
    RedisTemplate<String,Object> redisTemplate;

    @Autowired
    TestStockService testStockService;
/*    @Override
    public R buyShop(Integer num, Integer shopId) {
        //获取当前线程Id
        Long id =Thread.currentThread().getId();
        log.info("线程id="+id+"开始购买");
        //先判断锁是否已经被其他线程占据
        boolean isLock = getLock(shopId);
        if(!isLock){
            log.info("当前线程"+id+"在等待上一个线程处理完毕");
                try{
                     //没有获取，持续获取
                     while(!getLock(shopId)){
                        //没有获取线程，休眠一段时间获取，目的是和上一个线程的业务错开
                         //减少不必要的 cpu消耗
                         Thread.sleep(1000);
                     }

                }catch (Exception e){
                    log.error("出现异常");
                    e.printStackTrace();
                }
        }
        //-------获取到了锁，说明其他上一个线程的业务已经完成----------
        try {
            log.info("线程"+id+",获取到了锁,开始处理业务");
            //查询剩余库存
            int stockNum = testStockService.queryByShopId(shopId);

            if(stockNum==0){
                log.info("线程"+id+"处理完业务，没有抢购到商品");
                return R.error("商品库存已经卖完");
            }
            //减少库存
            int newStockNum = stockNum-num;
            if(newStockNum<0){
                return R.error("库存不足，商品库存只有"+stockNum+"个");
            }
            //更新库存
            TestStock t = new TestStock();
            t.setShopId(shopId);
            t.setNum(newStockNum);
            testStockService.updateByShopId(t);

            log.info("线程:"+id+"处理完业务,抢购到商品,商品剩余库存"+newStockNum);
            return R.ok("success",newStockNum);
        }catch (Exception e){
             log.error("出现异常");
             e.printStackTrace();
        }finally {
            log.info("线程"+id+"处理完业务，释放锁");
            //释放锁，就是删除这个键
            redisTemplate.delete("suo:"+shopId);
        }

      return R.error("错误");

    }*/

    /**
     * 获取锁
     * @param shopId
     * @return false 表示 key 存在,表示锁已经被其他线程占据
     */
    public Boolean getLock(Integer shopId){
        String key = "suo:"+shopId;
        String value = UUID.randomUUID()+"";
        // setIfAbsent方法解析:
        // 1.如果键不存在则新增,存在则不改变已经有的值。
        // 2.存在返回 false，不存在返回 true。
        return redisTemplate.opsForValue().setIfAbsent(key,value,60, TimeUnit.MINUTES);
    }

    @Override
    public R buyShop(Integer num, Integer shopId) {

        //获取当前线程Id
        Long id =Thread.currentThread().getId();
        log.info("线程id="+id+"开始购买");
        //查询
        int i = testStockService.queryByShopId(shopId);


        if(i>0){
            //更新库存
            TestStock t = new TestStock();
            t.setShopId(shopId);
            t.setNum(i-1);
            testStockService.updateByShopId(t);

            log.info("线程id="+id+"购买了商品1个,剩余"+(i-1));
        }else{
            log.info("线程id="+id+"没有购买到商品,库存不足");
            return R.error("库存不足");
        }


        return R.ok();
    }
}
